<?php
// +----------------------------------------------------------------------
// | 异步回调通知
// +----------------------------------------------------------------------
// | Author: @蓝优 荣誉出品
// +----------------------------------------------------------------------
class WxpayNotify
{
    private $logFile = "log.txt";

    // 日志记录函数，可添加日志级别
    public function log($level, $message)
    {
        $levels = array('INFO', 'WARNING', 'ERROR', 'SUCCESS');
        if (!in_array($level, $levels)) {
            throw new InvalidArgumentException("Invalid log level: " . $level);
        }
        $date = date('Y-m-d H:i:s');
        $logMessage = "[$date] $level: $message\n";
        
        // 检查文件是否存在，如果不存在则创建文件
        if (!file_exists($this->logFile)) {
            touch($this->logFile);
        }

        // 避免重复写入日志
        if (!$this->isLogWritten($logMessage)) {
            file_put_contents($this->logFile, $logMessage, FILE_APPEND);
        }
    }

    // 检查日志是否已经写入
    private function isLogWritten($logMessage)
    {
        $content = file_get_contents($this->logFile);
        return strpos($content, $logMessage) !== false;
    }

    // 接收微信支付通知
    public function getXml()
    {
        return file_get_contents("php://input");
    }

    // 验证签名
    public function checkSign($data, $key)
    {
        // 排序参数
        ksort($data);
        $str = "";
        // 拼接参数，跳过空值
        foreach ($data as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $str .= $k . "=" . $v . "&";
            }
        }
        // 添加商户密钥
        $str .= "key=" . $key;
        // 计算签名
        $sign = strtoupper(md5($str));
        // 验证签名
        return $data['sign'] == $sign;
    }

    // 处理通知
    public function handle($merchantKey)
    {
        // 读取通知数据
        $xml = $this->getXml();
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        // 验证签名
        if (!$this->checkSign($data, $merchantKey)) {
            $this->log('ERROR', 'Successfully paid. Data: ' . json_encode($data));
            return false;
        }

        // 处理业务逻辑
        if ($data['return_code'] == 'SUCCESS') {
            if ($data['result_code'] == 'SUCCESS') {
                // 支付成功
                $outTradeNo = $data['out_trade_no'];
                // TODO: 处理业务逻辑，例如更新订单状态等
                // 返回成功给微信服务器
                echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            } else {
                // 支付失败
                $this->log('WARNING', 'Payment failed. Error code: ' . $data['err_code'] . ', Error message: ' . $data['err_code_des']);
            }
        } else {
            // 通信失败
            $this->log('ERROR', 'Communication failed. Return message: ' . $data['return_msg']);
        }
    }
}

try {
    $notify = new WxpayNotify();
    $merchantKey = '你的密钥'; // 建议从配置文件或环境变量中读取
    $notify->handle($merchantKey);
} catch (Exception $e) {
    // 记录异常日志
    $notify->log('ERROR', 'Exception occurred: ' . $e->getMessage());
}